package com.globalwave.system.service;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.globalwave.base.BaseServiceImpl;
import com.globalwave.common.ArrayOrderList;
import com.globalwave.common.ArrayPageList;
import com.globalwave.common.Util;
import com.globalwave.common.cache.CodeHelper;
import com.globalwave.common.exception.BusinessException;
import com.globalwave.system.entity.Privilege;
import com.globalwave.system.entity.SessionUser;
import com.globalwave.system.entity.TerminalProfile;
import com.globalwave.system.entity.User;
import com.globalwave.system.entity.UserCriterion;
import com.globalwave.system.entity.UserOrganization;

public class UserServiceImpl extends BaseServiceImpl implements UserService {

    public ArrayPageList<User> query(
            UserCriterion userCriterion, 
            int pageIndex, 
            int pageSize,
            ArrayOrderList orderList) 
    throws Exception {
    	
        return (ArrayPageList<User>)jdbcDao.query(userCriterion, pageIndex, pageSize, orderList, User.class);
    }

    public void checkLoginIdUnified(User user) throws Exception {
        User old = new User() ;
        old.setLogin_id(user.getLogin_id()) ;
        
        old = (User)jdbcDao.find(old) ;
        
        if (old != null) {
        	throw new BusinessException("user.login.id.exist") ;
        }
    }

    public User create(User user, Long[] organization_ids) throws Exception { 
    	
    	checkLoginIdUnified(user) ;

        user.setPassword_(Util.hash(user.getPassword_())) ;
        
        User newUser = (User) jdbcDao.insert(user) ;
        
        if (organization_ids != null) {
            for (Long organization_id : organization_ids) {
                UserOrganization userOrg = new UserOrganization() ;
                userOrg.setUser_id(newUser.getUser_id()) ;
                userOrg.setOrganization_id(organization_id) ;
                jdbcDao.insert(userOrg) ;
            }
        }
        
        return newUser;
    }

    public void update(User user, Long[] organization_ids) throws Exception {

        if (StringUtils.isEmpty(user.getPassword_())) {
            user.addExclusions("password_") ;
        } else {
            user.setPassword_(Util.hash(user.getPassword_())) ;
        }

        user.addExclusions("login_id") ;// login_id is very import, can't be changed!
        
        jdbcDao.update(user);
        
        UserOrganization userOrg = new UserOrganization() ;
        userOrg.setUser_id(user.getUser_id()) ;
        jdbcDao.delete(UserOrganization.class,userOrg) ;
        
        if (organization_ids != null) {
            for (Long organization_id : organization_ids) {
                userOrg = new UserOrganization() ;
                userOrg.setUser_id(user.getUser_id()) ;
                userOrg.setOrganization_id(organization_id) ;
                jdbcDao.insert(userOrg) ;
            }
        }
    }

    public void changePassword(User user) throws Exception {

        if (StringUtils.isEmpty(user.getPassword_())) {
        	throw new BusinessException("no.password") ;
        }
        
        User user2 = (User)jdbcDao.get(SessionUser.get().getUser()) ;
        
        if (!Util.hash(user.getOld_password()).equals(user2.getPassword_())) {
        	throw new BusinessException("old.password.not.same") ;        	
        }
        
        user.setUser_id(user2.getUser_id()) ;
        user.setPassword_(Util.hash(user.getPassword_())) ;
        user.addInclusions("password_") ;

        jdbcDao.update(user) ;
        
    }
    public void delete(User user) throws Exception {
        
        UserOrganization userOrg = new UserOrganization() ;
        userOrg.setUser_id(user.getUser_id()) ;
        jdbcDao.delete(UserOrganization.class,userOrg) ;
        
        jdbcDao.delete(user) ;
        
    }

    public void deleteAll(Long[] userIds) throws Exception {
        
        UserCriterion criterion = new UserCriterion() ;
        criterion.setUserIds(userIds) ;
        
        // delete cascade
        jdbcDao.delete(UserOrganization.class, criterion) ;

        jdbcDao.delete(User.class, criterion) ;
        
    }

    public User find(Long user_id) throws Exception {
        User user = new User() ;
        user.setUser_id(user_id) ;
        
        ArrayPageList<User> list = (ArrayPageList<User>)
            jdbcDao.query(user, 1, Integer.MAX_VALUE, null, User.class);
        
        if (list.size() < 1) {
            return null ;
        } else {
            return list.get(0) ;
        }
    }

    public User findByLoginId(String login_id) throws Exception {
        User user = new User() ;
        user.setLogin_id(login_id) ;
        
        ArrayPageList<User> list = 
            (ArrayPageList<User>)jdbcDao.query(user, 1, Integer.MAX_VALUE, null, User.class);
        
        if (list.size() < 1) {
            return null ;
        } else {
            return list.get(0) ;
        }
    }

    
    public SessionUser login(User user, boolean isPosLogin) throws Exception {

    	String loginId = user.getLogin_id() ;
    	String password = user.getPassword_() ;
    	
        if (StringUtils.isBlank(loginId)){
        	throw new BusinessException("required", "loginId") ;
        }
        if(StringUtils.isBlank(password)) {
        	throw new BusinessException("required", "password") ;
        }

        User userResult = this.findByLoginId(user.getLogin_id());
        
        if (userResult == null) {
        	throw new BusinessException("E0000000001") ;
        } 
        
        SessionUser sessionUser = new SessionUser() ;
        sessionUser.setUser(userResult) ;
        
        /*
        if (this.getSysConfig().isUseSafeLogin()) {
            if (this.getLoginErrorService().isCanNotLogin(ui.getId())) {
                this.addActionError(this.getText("error.login.times"));
                return INPUT;
            }
        }*/

        if (!Util.hash(password).equals(userResult.getPassword_())) { 
        	
        	throw new BusinessException("E0000000004") ;
        }
        userResult.setPassword_(null) ;
        
        ArrayPageList<Privilege> privileges =
        	getPrivilegeService().getAllByUserId(userResult.getUser_id()) ;
        
        Set<Short> privilegeIds = new HashSet<Short>(privileges.size()) ;
        for (int i = privileges.size() - 1 ; i >= 0 ; i --) {
            privilegeIds.add(privileges.get(i).getCode_()) ;
        }
        sessionUser.setPrivilege_ids(privilegeIds) ;
        
        if (isPosLogin) {
        	TerminalProfile t = getTerminalProfileService().getLoginTerminalInfo(userResult) ;
        	sessionUser.setSale_date(t.getSale_date()) ;
        	sessionUser.setTerminal_code(t.getCode_()) ;
        }
        
        
    	return sessionUser ;
    }

    
    private TerminalProfileService getTerminalProfileService() {
    	return (TerminalProfileService)CodeHelper.getAppContext().getBean("terminalProfileService") ;
    }
    
    private PrivilegeService getPrivilegeService() {
    	return (PrivilegeService)CodeHelper.getAppContext().getBean("privilegeService") ;
    }
}
